<?php

namespace App\Http\Controllers\Api\Third;

use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use Illuminate\Support\Facades\Log;
use PHPUnit\Framework\Exception;


class RequestGwDataController extends Controller
{
    // private $url='http://22.40.212.237:8899/rmcp-gqj-web/api/';//接口对接地址
    private $url='';//接口对接地址
    private $orgId='';//试验中心组织机构id
    private $thirdMap=null;
    private $thirdId=null;
    private $blgSgsId=null; //试验中心所属市公司单位id
    private $timeout = null;
    private $third = null;

    public function __construct($third){
        $this->third = $third;
        $this->thirdId = $third->id;
        $this->url = $third->base_url;
        $this->orgId = $third->org_id;
        $this->blgSgsId = $third->blgSgsId;
    }

    //4. POST_安全工器具组织机构信息查询接口
    public function getOrgTree($orgId=''){
        $url = $this->url;
        $param = [
            'blgSgsId'=>$this->blgSgsId,
            'orgId'=>$orgId
        ];
        $this->timeout = 5;
        return '';  //没有组织机构接口，所以此处返回空值
        //return $this->requestData($url,$param);
    }
    //同步工器具名称
    public function getToolItems(){
        $url = $this->url;//获取检测工器具和检测项目信息的接口地址
        // dd($url);
        $param = json_encode(['orgId'=>$this->orgId]);//试验中心组织机构id
        $res =  $this->post_url($url,$param);//返回的数据

        // $res = file_get_contents(__DIR__."\\tool_data.json");//测试用返回的接口数据
        $res_data = json_decode($res,true);
        // dd($res_data);
        if (!$res_data) {
            return '连接'.$this->third->name.'服务器失败！';
        }
        $ret = 0;
        if ($res_data['successful']){
            $data = $res_data['resultValue'];
            $itemsNow = DB::table('a_third_testitem')->where('third_id',$this->thirdId)->get()->keyBy(function ($item)
                {
                    return $item->tool_id.'-'.$item->item_id;
                })->toArray();
            // dd($itemsNow);
            $inData = [];
            foreach ($data as $tool) {
                foreach ($tool['data'] as $item) {
                    $testList = data_get($item,'testList',[]);
                    // dd($testList);
                    foreach($testList as $item2){
                        if (!isset($itemsNow[$tool['gqjClassId'].'-'.$item2['pkDictDetailid']])) {
                            $inData[] = [
                                'third_id'=>$this->thirdId,
                                'tool_name'=>$tool['gqjClass'],
                                'tool_id'=>$tool['gqjClassId'],
                                'item_name'=>$item2['value'],
                                'item_id'=>$item2['pkDictDetailid'],
                            ];
                        }
                    }
                }
            }
            $ret = DB::table('a_third_testitem')->insert($inData);
        }
        return (int)$ret;
    }

    /**
     * 获取存量待检工器具列表
     * @param Request $request
     * 成功入库后在ThirdController.php文件中自动创建批次并添加样品
     */
    public function getGqjBookTestInfo($thirdMap){
        //获取映射关系
        $this->thirdMap = $thirdMap;
        //请求接口时传参
        $param = [];
        //url
        $url = $this->url;//试验中心通过组织机构查询风险监督平台安全工器具试验送检出库信息。

        $param['orgId']= $this->orgId; //试验中心组织机构id

        return $this->requestData($url,$param,'insert_third_data');

    }

    private function getVolClass($type){
        return DB::table('a_voltage_class')->where('type',$type)->get()->keyBy(function ($item) {
            // dd($item);
            return strtolower($item->std_id.'-'.$item->tool_id.'-'.$item->val);
        })->toArray();
    }

    /**
     * 插入第三方数据到数据库
     * @param $data
     * @param $contract_id
     * @return bool
     */
    public function insert_third_data($data,$thirdMap = null){
        if (!$data) {
            $msg = '工器具列表为空';
            Log::info('autoData/insert_third_data()'.$msg);
            return $msg;
        }
        $this->thirdMap = $thirdMap;        //赋值对应关系

        $thirdVols = array_get(array_get($thirdMap,0,[]),'third',[]);   //映射的电压等级
        $thirdTools = array_get(array_get($thirdMap,2,[]),'third',[]); //工器具类型
        $thirdStds = array_get(array_get($thirdMap,3,[]),'third',[]); //检测标准
        $thirdItems = array_get(array_get($thirdMap,4,[]),'third',[]); //检测项目

        $stds = DB::table('a_standard')->pluck('num','id');
        $item_id_rels = DB::table('a_std_tool_item_rel')->pluck('testitem_id','id')->toArray(); //试验项目id，对应的标准与工器具关系
        $inData = [];
        $total = 0;
        $vols= $this->getVolClass(0);   //获取电压、实验标准、工器具的关系
        $stdToolItems = $this->getStdToolItems();   //获取实验标准、工器具、试验项目的关系
        $data = $data ?: [];
        foreach ($data as $k=>$v){
            $info = DB::table('a_third_data')->where(['third_id'=>$this->thirdId,'third_id2'=>$v['kindId']])->orderBy('id','desc')->first();
            //判断样品库是否存在该样品，存在则跳过
            /*if($info){
                if(!$v['deleteFlag']){
                    //把这个工器具删除
                    $drow = DB::table('a_third_data')->where(['third_id'=>$this->thirdId,'third_id2'=>$v['kindId']])->delete;
                    continue;
                }
                if($info->third_pk_id != $v['prid']){
                    //不一样就修改prid为最新的
                    DB::table('a_third_data')->where(['third_id'=>$this->thirdId,'third_id2'=>$v['kindId']])->update(['third_pk_id'=>$v['prid']]);
                    Log::info('autoData/insert_third_data(): The third_pk_id of '.$v['kindId'].' Update to'.$v['prid']);
                }
                if(!$info->bar_code){
                    $inData[] = $info->id;
                    continue;
                }
                $exist = DB::table('a_sample_info as b')
                    ->leftJoin('a_contract as c','b.contract_id','=','c.id')
                    ->where('b.bar_code',$info->bar_code)
                    ->where('c.status','<',20)
                    ->exists();
                if($exist){
                    continue;
                }
            }*/

            /*对应工器具类型 start*/
            $toolMap = array_get($thirdTools,$v['gqjClass'],[]);
            if (!$toolMap) {
                $msg = "未对工器具{$toolMap['third_name']}做对照关系处理！";
                Log::info('autoData/insert_third_data() '.$msg);
                return $msg;
            }
            $tool_name = array_get($toolMap,'third_name',0);
            $tool_id = array_get($toolMap,'sys_id',0);
            /*对应工器具类型 end*/
            /*对应检测标准 start*/
            $std_name = array_get($toolMap,'third_id2','');
            $std_name = str_replace(' ','',$std_name);
            $standardArray = $thirdStds[$std_name];
            if(!$standardArray){
                $msg = "未对{$tool_name}检测标准{$v['gqjClass']}做对照关系处理！";
                Log::info('autoData/insert_third_data() '.$msg);
                return $msg;
            }
            $std_id = $standardArray['sys_id'];
            $std_num = $stds[$std_id];
            /*对应检测标准 end*/
            /*对应额定电压 start*/
            $third_vol = $v['voltageGrade'];
            //传的额定电压为空的话，xml会解析成个@attributes数组，需要处理下
            if(is_array($third_vol)){
                $third_vol = '';
            }
            $vol_id = 0;
            $volMap = [];
            $volMap = array_get($thirdVols,$third_vol,[]);
            if($v['checkType'] != 1) {  //送检类型(0电气试验1力学试验2电气试验和力学试验)
                if (!$volMap) {
                    $vol = array_get($vols, strtolower("{$std_id}-{$tool_id}-{$third_vol}"), []); //不对照直接取相同值
                    if (!$vol) { //如果没有相同值，插入新值
                        $std_tool_rel_id = DB::table('a_std_tool_rel')->where(['std_id' => $std_id, 'tool_id' => $tool_id])->value('id');
                        $vol_id = DB::table('a_voltage_class')->insertGetId(['type' => 0, 'std_id' => $std_id, 'tool_id' => $tool_id, 'std_tool_rel_id' => $std_tool_rel_id, 'val' => $third_vol]);
                        $vols = $this->getVolClass(0);
                    } else {
                        $vol_id = $vol->id;
                    }
                } else {
                    $sys_vol = array_get($volMap, 'sys_name', '');
                    $vol = array_get($vols, strtolower($std_id . '-' . $tool_id . '-' . $sys_vol), []);
                    $vol_id = data_get($vol, 'id', 0);
                }
                if (!$vol_id) {
                    $msg = "未对额定电压{$std_num}-{$tool_name}-{$sys_vol}做对照关系处理！";
                    Log::info('autoData/insert_third_data()' . $msg);
                    return $msg;
                }
            }
            /*对应额定电压 end*/

            /*试验项目 start*/
            $a_std_tool_item = DB::table('a_std_tool_item_rel')->where([['ishide',0],['std_id',$std_id],['tool_id',$tool_id]])->where('testitem_id','!=',61)->get();
            if(!$a_std_tool_item){
                $msg = "未设置{$std_num}-{$tool_name}-试验项目！";
                Log::info('autoData/insert_third_data()'.$msg);
                return $msg;
            }
            foreach($a_std_tool_item as $key=>$val){
                $yingsheItems = DB::table('a_third_map')->where([['type',4],['sys_id',$val->id]])->first();
                if(!$yingsheItems) {
                    $msg = "未映射{$std_num}标准<{$tool_name}>的<{$val->id}>试验项目！";
                    Log::info('autoData/insert_third_data()未映射{$std_num}标准<{$tool_name}>在a_std_tool_item_rel表的<{$val->id}>试验项目！');
                    return $msg;
                }
                if(!$val->station_ids){
                    $msg = "未绑定{$std_num}标准<{$tool_name}>的<{$val->id}>试验设备！";
                    Log::info('autoData/insert_third_data()未绑定{$std_num}标准<{$tool_name}>在a_std_tool_item_rel表的<{$val->id}>试验设备！');
                    return $msg;
                }
            }
            /*试验项目 end*/
            $sysItems = array_get($stdToolItems,$std_id.'-'.$tool_id,[]);
            $item = [
                'std_id'=>$std_id,
                'std_num'=>$std_num,
                'third_id'=>$this->thirdId,
                'third_pk_id'=>$v['prid'],
                'third_id2'=>$v['kindId'],
                'third_tool_name'=>$v['gqjClass'],
                'tool_id'=>$tool_id ?: 0,
                'tool_name'=>array_get($toolMap,'sys_name',''),
                'guige_xinghao'=>$v['gqjStandard'],
                'third_voltage'=>$third_vol,
                'voltage'=>array_get($volMap,'sys_name',''),
                'class'=>$v['blgProvince'],
                'vol_id'=>$vol_id ?: 0,
                'self_num'=>$v['kindId'],  //和客户沟通后，客户要求用icode
                'third_status'=>$v['deleteFlag'],  //删除还是保留
                'check_type'=>$v['checkType'], //送检类型(0电气试验1力学试验2电气试验和力学试验)
                'upload'=>array_get($toolMap,'upload',1),
                'item_ids'=>implode(',',array_column($sysItems,'item_id')), //本系统做试验
                'item_names'=>implode(',',array_column($sysItems,'item_name')), //本系统做试验
                'send_time'=>str_replace('-', '', array_get($v,'sendTime')) ?: 0
            ];

            $total += 1;
            $inData[] = DB::table('a_third_data')->insertGetId($item);
        }

        return $inData ? $inData : '或已存在该数据！';
    }

    /**
     * 将实验数据上传到风控平台 安全工器具试验结果保存接口
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|void
     */
    public function saveGqjBookTestInfo($thirdMap){
        $request = request();
        $url = $this->url;
        $sampleIds  = request('sample_ids',[]);//获取要上传的实验数据的ID
        $params = [];
        $thirdId = $request->third_ids;
        $company = DB::table('a_third')->where('id',$thirdId[0])->value('org_id');
        foreach ($sampleIds as $sampleId) {
            $param = $this->getUpSampleParam($sampleId,$company);
            if(!is_array($param)){
                return $param;
            }
            $params[] = $param;
        }
        //拼装soap的xml
        $xml_str = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.sgcc.com/"><soapenv:Header/><soapenv:Body><web:saveExperimentData><param><![CDATA[ <o><items class="array">';
        foreach($params as $gqjkey=>$gqjInfos){
            $xml_str .= '<item class="object">';
            foreach($gqjInfos as $gqjk=>$gqjInfo){
                if($gqjk != 'testData'){
                    $xml_str .= '<'.$gqjk.' type="string">'.$gqjInfo.'</'.$gqjk.'>';
                }
                if($gqjk == 'testData'){
                    $xml_str .= '<testDataArray class="array">';
                    foreach($gqjInfo as $itemkey=>$itemdata){
                        $xml_str .= '<testData class="object">';
                        foreach($itemdata as $datakey=>$dataval){
                            $xml_str .= '<'.$datakey.' type="string">'.$dataval.'</'.$datakey.'>';
                        }
                        $xml_str .= '</testData>';
                    }
                    $xml_str .= '</testDataArray>';
                }
            }
            $xml_str .= '</item>';
        }
        $xml_str .= '</items></o>]]></param></web:saveExperimentData></soapenv:Body></soapenv:Envelope>';
        Log::info('upload_to_Risk_Data:'.$xml_str);
        $uploadRes =  $this->requestData($url,$xml_str);
        //上传成功后修改样品状态为已提交
        if($uploadRes == 1){
            foreach ($sampleIds as $sid) {
                DB::table('a_sample_info')->where('id', $sid)->where('status0',0)->update(['status0' => 1]);
            }
        }
        return $uploadRes;

    }

    private function requestData($url,$params = [],$sucBakFunc=''){
        $res = $this->post_url($url,$params);
        if(!$res){
            $msg = "autoData/getThirdDj/getGqjBookTestInfo/requestData(),请求超时，请检查！！";
            Log::info($msg);
            return $msg;
        }
        //$res = str_replace(array("\r","\n"),'',$res);
        $dom = new \DOMDocument();
        $dom->loadXML($res);
        $root = $dom->documentElement;
        $content = $dom->getElementsByTagName('return');
        $cdata = $content->item(0)->nodeValue;
        $Toolxml = json_encode(simplexml_load_string($cdata));
        $Toolxml = json_decode($Toolxml,true);
        $suc = $Toolxml['successful'];
        if ($suc == 'true'){
            return 1;
        }else{
            $msg = '上传风控失败：'.json_encode($Toolxml['resultValue']['items']['e']);
            return $msg;
        }
    }

    private function getUpSampleParam($id,$company){
        $sample =  DB::table('a_sample_info as B')
                ->leftJoin('a_contract_gaiyao as A', 'A.id', '=', 'B.contract_gaiyao_id')
                ->leftJoin('a_contract as C', 'A.contract_id', '=', 'C.id')
                ->leftJoin('a_third_data as d', 'B.bar_code', '=', 'd.bar_code')
                ->where('B.id', $id)
                ->select(['d.third_book_id','d.third_pk_id','d.third_id as a_third_id','B.contract_id','B.contract_gaiyao_id','B.tester_names','d.third_status','A.tool_id','A.std_id',"B.test_time",'B.next_time','C.batchNum','B.bar_code','B.third_id','d.third_fac_num','d.third_voltage','A.class_id','A.class','A.vol_id'])
                ->first();//查询上传数据的关联信息。合同Id工器具id 实验项目id
        if(!$sample){
            return '没查到该样品！';
        }
        //组建上传数据
        $param= [
            'TOKEN'=>$company
        ];
        $thirdItemDatas = []; //初始化 key:本系统项目 value:第三方平台数据
        /*获取本系统项目第三方试验数据 start*/
            $inputDatas = DB::table('a_input_data as a')
                ->leftJoin('a_testdata_key as b','a.testdata_key_id','=','b.id')
                ->leftJoin('a_third_map as c',function($query)use($sample){
                    $query->where('c.third_id',$sample->a_third_id)->where('c.type',5)->on('c.sys_id','=','a.testdata_key_id');
                })
                ->select('a.*','b.item_id','c.third_id2 as third_id','c.third_name','c.formula','b.data_key','c.times')
                ->where('a.sample_info_id',$id)
                ->where('c.upload',1)
                ->orderBy('c.times','asc')
                // ->where('c.third_name','!=','') //计算的时候可能会用到相关值，所以这里去掉查询
                ->get()->toArray();
            $item_inputs = [];  //初始化 本系统项目数据 和 第三方平台项目数据
            foreach ($inputDatas as $item) {
                $item_inputs[$item->item_id][$item->data_key] = $item;
            }
            foreach ($item_inputs as $item_id => &$inputs) {
                /*将需要计算的值计算出来 start*/
                    $formulas = array_filter(array_column($inputs,'formula','data_key'));
                    foreach ($formulas as $data_key => &$formula) {
                        if($formula == 'class'){
                            $class = $sample->class;
                            $inputs[$data_key]->val = is_numeric(substr($class,0,1)) ? (int)$class : $class ;
                            // dd($inputs);
                        }else{
                            foreach($inputs as $data_key_input => $inputItem){
                                $val = is_numeric($inputItem->val) ? $inputItem->val : 0;
                                $formula = str_replace($data_key_input, $val, $formula);
                            }
                            try{
                                eval("\$val = $formula;");
                            }catch(\Exception $e){
                                $val = '';
                            }
                            $inputs[$data_key]->val = $val;
                        }
                    }
                /*将需要计算的值计算出来 end*/
                /*将对照过的数据添加到 $thirdItemDatas start*/
                    foreach ($inputs as $input) {
                        if($input->third_name){
                            $val = is_numeric($input->val) ? $input->val : '/';
                            $thirdItemDatas[$item_id]['TEST'.$input->times] = $val;
                        }
                    }
                /*将对照过的数据添加到 $thirdItemDatas end*/
            }
            unset($formula,$inputs);
        /*获取本系统项目第三方试验数据 end*/
        $test_item_data = DB::table('a_item_data as a')
            ->leftJoin('a_testitem as b','a.item_id','=','b.id')
            ->leftJoin('a_contract_gaiyao as g','a.contract_gaiyao_id','=','g.id')
            ->leftJoin('manager as m','a.manager_id','=','m.id')
            ->leftJoin('a_std_tool_item_rel as r',function ($query)
            {
                $query->on('r.std_id','=','g.std_id')->on('r.tool_id','=','g.tool_id')->on('r.testitem_id','=','a.item_id');
            })
            ->leftJoin('a_third_map as h',function ($query)use($sample)
            {
                $query->on('r.id','=','h.sys_id')->where('h.third_id',$sample->a_third_id)->where('type',4);
            })
            ->where('a.item_id','!=',61)                //外观检测结果不需要上传
            ->where('h.upload',1)
            ->where('a.sample_info_id',$id)
            ->select(['a.*','m.realname','b.name as tool_name','h.third_id2','h.third_name'])
            ->wherein('a.res',[0,1])->get();

        /*处理检测设备*/
        $station_ids = [];
        $dev_num = '';
        $dev_name = '';
        foreach($test_item_data as $kdev=>$devv){
            $station_ids =array_merge($station_ids,explode(',',$devv->station_ids));
            $station_ids = array_unique($station_ids);
        }
        $devInfo = DB::table('a_station')->whereIn('id',$station_ids)->select('spec','name')->get()->toArray();
        if($devInfo){
            $dev_name = implode(',',array_column($devInfo,'name'));
            $dev_num = implode(',',array_column($devInfo,'spec'));
        }
        $test_arr =[];
        foreach ($test_item_data as $k=>$v){
            /*试验数据基本内容、文件内容*/
            $testResult = (string)(1-$v->res);//风控平台跟我们的结果相反。直接取反
            $thirdInputs = data_get($thirdItemDatas,$v->item_id,[]);
            if($thirdInputs) {
                $thirdInputs['testProject'] = $v->third_name;      //试验项目
                $thirdInputs['projectResult'] = $testResult;       //结论
            }
            $testData[$k] = $thirdInputs;
            $gqjCheckResultList = [
                'prid'=>$sample->third_pk_id, //送检主键id
                'inspectDate'=>$v->utime,
                'inspectTemp'=>$v->temp,
                'inspectHumidity'=>$v->hum, //环境湿度%
                'inspectPressure'=>$v->pressure, //环境气压kPa
                'inspectEquipment'=>$dev_name, //检测设备名称
                'inspectModel'=>$dev_num, //设备编号
                'testData'=>$testData
            ];
            $test_arr[]=$gqjCheckResultList;
        }

        $param['testList']=$test_arr;
        return $gqjCheckResultList;
    }

    protected function post_url($url,$data){
         /*if (isAdmin()) {
             return file_get_contents('./ddzy.json');
             if(strstr($url, 'getOrgTree')){
                 return file_get_contents(__DIR__.'/gw_org.json');
             }
             if(strstr($url, 'getGqjTestInfo')){
                 return file_get_contents(__DIR__.'/gw_stock.json');
             }
             return 222222222;
         }*/
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_POST,1);
        curl_setopt($ch,CURLOPT_URL,$url);
        if (!is_null($this->timeout)) {
            curl_setopt($ch,CURLOPT_TIMEOUT,$this->timeout);
        }
        curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch,CURLOPT_HEADER,false);
        //curl_setopt($ch,CURLOPT_HTTPHEADER,['Content-Type:application/json;charset=UTF-8']);
        curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type:text/xml; charset=utf-8"));
        $res = curl_exec($ch);
        curl_close($ch);
        return $res;
    }

    private function getStdToolItems($std_id=0,$tool_id=0){
        $data = DB::table('a_std_tool_item_rel as a')
                ->leftJoin('a_testitem as b','a.testitem_id','=','b.id')
                ->where(['a.ishide'=>0])
                ->select('a.id as id','b.id as item_id','b.name as item_name','a.std_id','a.tool_id')
                ->orderBy('a.sort','asc')
                ->get();
        $data2 = [];
        foreach ($data as $item) {
            $data2[$item->std_id.'-'.$item->tool_id][] = $item;
        }
        if ($std_id && $tool_id) {
            return $data2[$std_id.'-'.$tool_id];
        }
        // dd($data2);
        return $data2;
    }

}
